import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketTimeoutException;


/**
 * Authors - Oren Bracha, Rony Lahav and Yehuda Eterman
 * 
 * this class manages the UDP connections for input and output
 *
 */
public class UDPManager implements Runnable {
	// This method is responsible for listening to the specific client and inform the server
	// for every data got from the client
	public void run()
	{
		boolean stillHasToRun = true;
		
		int myPort = -1;
		int counter = 1;
		DatagramSocket serverDS = null;
		
		do {
			try	
			{
				// Try to listen for incoming udp connection
				if (myPort != proj350.getMyUDPPort()){
					myPort = proj350.getMyUDPPort();
					if (serverDS != null && !serverDS.isClosed()){
						serverDS.close();
					}
					serverDS = new DatagramSocket(myPort);
				}
				
				// Preparing the buffer for receiving the first message (which should be an update message of course)
				byte[] buffer = new byte[1024];
				DatagramPacket rcvPacket = new DatagramPacket(buffer, buffer.length);
				
				// If i'm still waiting for a udp connection in order to determine if to run or not 
				if (proj350.inTrialMode && counter <= proj350.CONN_ESTABLISH_ATTEMPTS_NUMBER)
				{
					++counter;
					// Set the timeout for updatefrequency seconds
					serverDS.setSoTimeout(proj350.getUpdateFrequency()*1000);
					
					
					// Try to receive a packet
					serverDS.receive(rcvPacket);
					
					proj350.inTrialMode = false;
					
					// I got an update, I'm going to turn on the updater thread (if it was'nt turned on yet)
					if (!proj350.updaterThread.isAlive()){
						proj350.updaterThread.start();
					}
				}
				else
				{
					// not in trial mode
					serverDS.setSoTimeout(proj350.MANAGER_REFRESH_TIME);
					serverDS.receive(rcvPacket);
					proj350.inTrialMode = false;
				}

				//start the UDPReceiverConnection thread to handle the current connection 
				int senderPort = rcvPacket.getPort();
				UDPReceiverConnection udpConnRec = new UDPReceiverConnection(proj350.getNewUniqueID(), senderPort,rcvPacket, rcvPacket.getAddress().getHostAddress());
				Thread thread = new Thread(udpConnRec);
				proj350.addThreadToLivingList(udpConnRec.getUniqueID(), thread);
				thread.start();
			}
			catch(SocketTimeoutException e1){
				//shut down if this is the first time we are connecting to someone
				if (proj350.inTrialMode && counter == proj350.CONN_ESTABLISH_ATTEMPTS_NUMBER){
					stillHasToRun = false;
					proj350.shutDown = true;
				}
			}
			catch(IOException e2)
			{
			}
			
			try{
				if (proj350.getSleepPeriod() > 0){
					Thread.sleep(proj350.getSleepPeriod()*1000);
				}
			}
			catch (InterruptedException e){
			}
		} while (!proj350.isShutDown() && stillHasToRun); // while not shut down
		
		if (serverDS != null && !serverDS.isClosed()){
			serverDS.close();
		}
	}
	
}
